home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / dflat8.zip / LISTBOX.C < prev    next >
Text File  |  1991-09-30  |  11KB  |  469 lines

  1. /* ------------- listbox.c ------------ */
  2.  
  3. #include "dflat.h"
  4.  
  5. static int ExtendSelections(WINDOW, int, int);
  6. static void TestExtended(WINDOW, PARAM);
  7. static void ClearAllSelections(WINDOW);
  8. static void SetSelection(WINDOW, int);
  9. static void FlipSelection(WINDOW, int);
  10. static void ClearSelection(WINDOW, int);
  11. static void near writeselection(WINDOW, int, int, RECT *);
  12. static void near change_selection(WINDOW, int, int);
  13. static int near selection_in_window(WINDOW, int);
  14.  
  15. static int py = -1;
  16.  
  17. static int LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  18. {
  19.     int my = (int) p2 - GetTop(wnd);
  20.     if (my >= wnd->wlines-wnd->wtop)
  21.         my = wnd->wlines - wnd->wtop;
  22.  
  23.     if (WindowMoving || WindowSizing)
  24.         return FALSE;
  25.     if (!InsideRect(p1, p2, ClientRect(wnd)))
  26.         return FALSE;
  27.     if (wnd->wlines && my != py)    {
  28.         int sel = wnd->wtop+my-1;
  29.         int sh = getshift();
  30.         if (!(sh & (LEFTSHIFT | RIGHTSHIFT)))    {
  31.             if (!(sh & CTRLKEY))
  32.                 ClearAllSelections(wnd);
  33.             wnd->AnchorPoint = sel;
  34.             SendMessage(wnd, PAINT, 0, 0);
  35.         }
  36.         SendMessage(wnd, LB_SELECTION, sel, TRUE);
  37.         py = my;
  38.     }
  39.     return TRUE;
  40. }
  41.  
  42. static int DoubleClickMsg(WINDOW wnd, PARAM p1, PARAM p2)
  43. {
  44.     if (WindowMoving || WindowSizing)
  45.         return FALSE;
  46.     if (wnd->wlines)    {
  47.         RECT rc = ClientRect(wnd);
  48.         BaseWndProc(LISTBOX, wnd, DOUBLE_CLICK, p1, p2);
  49.         if (InsideRect(p1, p2, rc))
  50.             SendMessage(wnd, LB_CHOOSE,
  51.                 wnd->selection, 0);
  52.     }
  53.     return TRUE;
  54. }
  55.  
  56. static void BorderMsg(WINDOW wnd)
  57. {
  58.     if (isMultiLine(wnd))    {
  59.         char ttl[80] = "";
  60.         WINDOW wnd1 = wnd;
  61.         char *cp;
  62.         if (!TestAttribute(wnd1, HASTITLEBAR))    {
  63.             if ((wnd1 = GetParent(wnd)) == NULL)
  64.                 return;
  65.             if (!TestAttribute(wnd1, HASTITLEBAR))
  66.                 return;
  67.         }
  68.         if (wnd1->title)
  69.             strcpy(ttl, wnd1->title);
  70.         if ((cp = strstr(ttl, " (Add)")) != NULL)
  71.             *cp = '\0';
  72.         if (wnd->AddMode)
  73.             /* ---- in Add mode ---- */
  74.             strcat(ttl, " (Add)");
  75.         InsertTitle(wnd1, ttl);
  76.         if (wnd != wnd1)
  77.             SendMessage(wnd1, BORDER, 0, 0);
  78.     }
  79. }
  80.  
  81. static int AddTextMsg(WINDOW wnd, PARAM p1, PARAM p2)
  82. {
  83.     int rtn = BaseWndProc(LISTBOX, wnd, ADDTEXT, p1, p2);
  84.     if (wnd->selection == -1)
  85.         SendMessage(wnd, LB_SETSELECTION, 0, 0);
  86.     if (*(char *)p1 == LISTSELECTOR)
  87.         wnd->SelectCount++;
  88.     return rtn;
  89. }
  90.  
  91. static void AddModeKey(WINDOW wnd)
  92. {
  93.     if (isMultiLine(wnd))    {
  94.         wnd->AddMode ^= TRUE;
  95.         SendMessage(GetParent(wnd), ADDSTATUS,
  96.             wnd->AddMode ? ((PARAM) "Add Mode") : 0, 0);
  97.     }
  98. }
  99.  
  100. static void UpKey(WINDOW wnd, PARAM p2)
  101. {
  102.     if (wnd->selection > 0)    {
  103.         if (wnd->selection == wnd->wtop)    {
  104.             writeselection(wnd, wnd->selection, FALSE, NULL);
  105.             BaseWndProc(LISTBOX, wnd, KEYBOARD, UP, p2);
  106.             PostMessage(wnd, LB_SELECTION, wnd->selection-1,
  107.                 isMultiLine(wnd) ? p2 : FALSE);
  108.         }
  109.         else    {
  110.             int newsel = wnd->selection-1;
  111.             if (wnd->wlines == ClientHeight(wnd))
  112.                 while (*TextLine(wnd, newsel) == LINE)
  113.                     --newsel;
  114.             PostMessage(wnd, LB_SELECTION, newsel,
  115.                 isMultiLine(wnd) ? p2 : FALSE);
  116.         }
  117.     }
  118. }
  119.  
  120. static void DnKey(WINDOW wnd, PARAM p2)
  121. {
  122.     if (wnd->selection < wnd->wlines-1)    {
  123.         if (wnd->selection == wnd->wtop+ClientHeight(wnd)-1)    {
  124.             writeselection(wnd, wnd->selection, FALSE, NULL);
  125.             BaseWndProc(LISTBOX, wnd, KEYBOARD, DN, p2);
  126.             PostMessage(wnd, LB_SELECTION, wnd->selection+1,
  127.                 isMultiLine(wnd) ? p2 : FALSE);
  128.         }
  129.         else    {
  130.             int newsel = wnd->selection+1;
  131.             if (wnd->wlines == ClientHeight(wnd))
  132.                 while (*TextLine(wnd, newsel) == LINE)
  133.                     newsel++;
  134.             PostMessage(wnd, LB_SELECTION, newsel,
  135.                 isMultiLine(wnd) ? p2 : FALSE);
  136.         }
  137.     }
  138. }
  139.  
  140. static void HomePgUpKey(WINDOW wnd, PARAM p1, PARAM p2)
  141. {
  142.     BaseWndProc(LISTBOX, wnd, KEYBOARD, p1, p2);
  143.     PostMessage(wnd, LB_SELECTION, wnd->wtop,
  144.         isMultiLine(wnd) ? p2 : FALSE);
  145. }
  146.  
  147. static void EndPgDnKey(WINDOW wnd, PARAM p1, PARAM p2)
  148. {
  149.     int bot;
  150.     BaseWndProc(LISTBOX, wnd, KEYBOARD, p1, p2);
  151.     bot = wnd->wtop+ClientHeight(wnd)-1;
  152.     if (bot > wnd->wlines-1)
  153.         bot = wnd->wlines-1;
  154.     PostMessage(wnd, LB_SELECTION, bot,
  155.         isMultiLine(wnd) ? p2 : FALSE);
  156. }
  157.  
  158. static void SpacebarKey(WINDOW wnd, PARAM p2)
  159. {
  160.     if (isMultiLine(wnd))    {
  161.         int sel = SendMessage(wnd, LB_CURRENTSELECTION, 0, 0);
  162.         if (sel != -1)    {
  163.             if (wnd->AddMode)
  164.                 FlipSelection(wnd, sel);
  165.             else     {
  166.                 ClearAllSelections(wnd);
  167.                 SetSelection(wnd, sel);
  168.             }
  169.             if (!((int) p2 & (LEFTSHIFT | RIGHTSHIFT)))
  170.                 wnd->AnchorPoint = sel;
  171.             if (ItemSelected(wnd, sel))
  172.                 ExtendSelections(wnd, sel, (int) p2);
  173.             SendMessage(wnd, PAINT, 0, 0);
  174.         }
  175.     }
  176. }
  177.  
  178. static void EnterKey(WINDOW wnd)
  179. {
  180.     if (wnd->selection != -1)    {
  181.         SendMessage(wnd, LB_SELECTION, wnd->selection, TRUE);
  182.         SendMessage(wnd, LB_CHOOSE, wnd->selection, 0);
  183.     }
  184. }
  185.  
  186. static void KeyPress(WINDOW wnd, PARAM p1, PARAM p2)
  187. {
  188.     int sel = wnd->selection+1;
  189.     while (sel < wnd->wlines)    {
  190.         char *cp = TextLine(wnd, sel);
  191.         if (cp == NULL)
  192.             break;
  193.         if (isMultiLine(wnd))
  194.             cp++;
  195.         /* --- special for directory list box --- */
  196.         if (*cp == '[')
  197.             cp++;
  198.         if (tolower(*cp) == (int)p1)    {
  199.             SendMessage(wnd, LB_SELECTION, sel,
  200.                 isMultiLine(wnd) ? p2 : FALSE);
  201.             if (!selection_in_window(wnd, sel))    {
  202.                 wnd->wtop = sel-ClientHeight(wnd)+1;
  203.                 SendMessage(wnd, PAINT, 0, 0);
  204.             }
  205.             break;
  206.         }
  207.         sel++;
  208.     }
  209. }
  210.  
  211. static int KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  212. {
  213.     switch ((int) p1)    {
  214.         case SHIFT_F8:
  215.             AddModeKey(wnd);
  216.             return TRUE;
  217.         case UP:
  218.             TestExtended(wnd, p2);
  219.             UpKey(wnd, p2);
  220.             return TRUE;
  221.         case DN:
  222.             TestExtended(wnd, p2);
  223.             DnKey(wnd, p2);
  224.             return TRUE;
  225.         case PGUP:
  226.         case HOME:
  227.             TestExtended(wnd, p2);
  228.             HomePgUpKey(wnd, p1, p2);
  229.             return TRUE;
  230.         case PGDN:
  231.         case END:
  232.             TestExtended(wnd, p2);
  233.             EndPgDnKey(wnd, p1, p2);
  234.             return TRUE;
  235.         case ' ':
  236.             SpacebarKey(wnd, p2);
  237.             break;
  238.         case '\r':
  239.             EnterKey(wnd);
  240.             return TRUE;
  241.         default:
  242.             KeyPress(wnd, p1, p2);
  243.             break;
  244.     }
  245.     return FALSE;
  246. }
  247.  
  248. static void GetTextMsg(WINDOW wnd, PARAM p1, PARAM p2)
  249. {
  250.     if ((int)p2 != -1)    {
  251.         char *cp1 = (char *)p1;
  252.         char *cp2 = TextLine(wnd, (int)p2);
  253.         while (cp2 && *cp2 && *cp2 != '\n')
  254.             *cp1++ = *cp2++;
  255.         *cp1 = '\0';
  256.     }
  257. }
  258.  
  259. static int PaintMsg(WINDOW wnd, PARAM p1, PARAM p2)
  260. {
  261.     if (isVisible(wnd) && wnd->wlines)    {
  262.         BaseWndProc(LISTBOX, wnd, PAINT, p1, p2);
  263.         if (isMultiLine(wnd))    {
  264.             int sel = 0;
  265.             for (sel = 0; sel < wnd->wlines; sel++)    {
  266.                 if (ItemSelected(wnd, sel))
  267.                     writeselection(wnd, sel, TRUE, (RECT *)p1);
  268.             }
  269.         }
  270.         writeselection(wnd, wnd->selection, TRUE, (RECT *)p1);
  271.         return TRUE;
  272.     }
  273.     return FALSE;
  274. }
  275.  
  276. int ListBoxProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  277. {
  278.     switch (msg)    {
  279.         case CREATE_WINDOW:
  280.             BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  281.             wnd->selection = -1;
  282.             wnd->AnchorPoint = -1;
  283.             return TRUE;
  284.         case KEYBOARD:
  285.             if (WindowMoving || WindowSizing)
  286.                 break;
  287.             if (KeyboardMsg(wnd, p1, p2))
  288.                 return TRUE;
  289.             break;
  290.         case BUTTON_RELEASED:
  291.             if (WindowMoving || WindowSizing || HSliding || VSliding)
  292.                 break;
  293.             py = -1;
  294.             return TRUE;
  295.         case LEFT_BUTTON:
  296.             if (LeftButtonMsg(wnd, p1, p2) == TRUE)
  297.                 return TRUE;
  298.             break;
  299.         case DOUBLE_CLICK:
  300.             if (DoubleClickMsg(wnd, p1, p2))
  301.                 return TRUE;
  302.             break;
  303.         case BORDER:
  304.             BorderMsg(wnd);
  305.             break;
  306.         case ADDTEXT:
  307.             return AddTextMsg(wnd, p1, p2);
  308.         case CLEARTEXT:
  309.             wnd->selection = -1;
  310.             wnd->AnchorPoint = -1;
  311.             wnd->SelectCount = 0;
  312.             break;
  313.         case SCROLL:
  314.             BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  315.             if ((int)p2 == FALSE)
  316.                 writeselection(wnd, wnd->selection, TRUE, NULL);
  317.             return TRUE;
  318.         case LB_CHOOSE:
  319.             SendMessage(GetParent(wnd), msg, p1, p2);
  320.             break;
  321.         case LB_SETSELECTION:
  322.             change_selection(wnd, (int) p1, 0);
  323.             return TRUE;
  324.         case LB_SELECTION:
  325.             change_selection(wnd, (int) p1, (int) p2);
  326.             SendMessage(GetParent(wnd), LB_SELECTION, wnd->selection, 0);
  327.             return TRUE;
  328.         case LB_CURRENTSELECTION:
  329.             return wnd->selection;
  330.         case LB_GETTEXT:
  331.             GetTextMsg(wnd, p1, p2);
  332.             return TRUE;
  333.         case PAINT:
  334.             if (PaintMsg(wnd, p1, p2))
  335.                 return TRUE;
  336.             break;
  337.         case HORIZSCROLL:
  338.             return TRUE;
  339.         case CLOSE_WINDOW:
  340.             if (isMultiLine(wnd) && wnd->AddMode)    {
  341.                 wnd->AddMode = FALSE;
  342.                 SendMessage(GetParent(wnd), ADDSTATUS, 0, 0);
  343.             }
  344.             break;
  345.         default:
  346.             break;
  347.     }
  348.     return BaseWndProc(LISTBOX, wnd, msg, p1, p2);
  349. }
  350.  
  351.  
  352. static void TestExtended(WINDOW wnd, PARAM p2)
  353. {
  354.     if (isMultiLine(wnd) && !wnd->AddMode &&
  355.             !((int) p2 & (LEFTSHIFT | RIGHTSHIFT)))    {
  356.         if (wnd->SelectCount > 1)    {
  357.             ClearAllSelections(wnd);
  358.             SendMessage(wnd, PAINT, 0, 0);
  359.         }
  360.     }
  361. }
  362.  
  363. static void ClearAllSelections(WINDOW wnd)
  364. {
  365.     if (isMultiLine(wnd) && wnd->SelectCount > 0)    {
  366.         int sel;
  367.         for (sel = 0; sel < wnd->wlines; sel++)
  368.             ClearSelection(wnd, sel);
  369.     }
  370. }
  371.  
  372. static void FlipSelection(WINDOW wnd, int sel)
  373. {
  374.     if (isMultiLine(wnd))    {
  375.         if (ItemSelected(wnd, sel))
  376.             ClearSelection(wnd, sel);
  377.         else
  378.             SetSelection(wnd, sel);
  379.     }
  380. }
  381.  
  382. static int ExtendSelections(WINDOW wnd, int sel, int shift)
  383. {    
  384.     if (shift & (LEFTSHIFT | RIGHTSHIFT) &&
  385.                         wnd->AnchorPoint != -1)    {
  386.         int i = sel;
  387.         int j = wnd->AnchorPoint;
  388.         int rtn;
  389.         if (j > i)
  390.             swap(i,j);
  391.         rtn = i - j;
  392.         while (j <= i)
  393.             SetSelection(wnd, j++);
  394.         return rtn;
  395.     }
  396.     return 0;
  397. }
  398.  
  399. static void SetSelection(WINDOW wnd, int sel)
  400. {
  401.     if (isMultiLine(wnd) && !ItemSelected(wnd, sel))    {
  402.         char *lp = TextLine(wnd, sel);
  403.         *lp = LISTSELECTOR;
  404.         wnd->SelectCount++;
  405.     }
  406. }
  407.  
  408. static void ClearSelection(WINDOW wnd, int sel)
  409. {
  410.     if (isMultiLine(wnd) && ItemSelected(wnd, sel))    {
  411.         char *lp = TextLine(wnd, sel);
  412.         *lp = ' ';
  413.         --wnd->SelectCount;
  414.     }
  415. }
  416.  
  417. int ItemSelected(WINDOW wnd, int sel)
  418. {
  419.     if (isMultiLine(wnd) && sel < wnd->wlines)    {
  420.         char *cp = TextLine(wnd, sel);
  421.         return (int)((*cp) & 255) == LISTSELECTOR;
  422.     }
  423.     return FALSE;
  424. }
  425.  
  426. static int near selection_in_window(WINDOW wnd, int sel)
  427. {
  428.     return (wnd->wlines && sel >= wnd->wtop &&
  429.             sel < wnd->wtop+ClientHeight(wnd));
  430. }
  431.  
  432. static void near writeselection(WINDOW wnd, int sel, int reverse, RECT *rc)
  433. {
  434.     if (isVisible(wnd))
  435.         if (selection_in_window(wnd, sel))
  436.             WriteTextLine(wnd, rc, sel, reverse);
  437. }
  438.  
  439. static void near change_selection(WINDOW wnd, int sel, int shift)
  440. {
  441.     if (sel != wnd->selection)    {
  442.         if (isMultiLine(wnd))        {
  443.             int sels;
  444.             if (!wnd->AddMode)
  445.                 ClearAllSelections(wnd);
  446.             sels = ExtendSelections(wnd, sel, shift);
  447.             if (sels > 1)
  448.                 SendMessage(wnd, PAINT, 0, 0);
  449.             if (sels == 0 && !wnd->AddMode)    {
  450.                 ClearSelection(wnd, wnd->selection);
  451.                 SetSelection(wnd, sel);
  452.                 wnd->AnchorPoint = sel;
  453.             }
  454.         }
  455.         writeselection(wnd, wnd->selection,
  456.                 isMultiLine(wnd) ?
  457.                 ItemSelected(wnd, wnd->selection) :
  458.                 FALSE,
  459.                 NULL);
  460.         wnd->selection = sel;
  461.         writeselection(wnd, sel,
  462.                 (isMultiLine(wnd) && wnd->AddMode) ?
  463.                 !ItemSelected(wnd, sel) :
  464.                 TRUE,
  465.                 NULL);
  466.         
  467.     }
  468. }
  469.